package com.batata.continuing.config.count.ip;

import com.batata.continuing.config.RedisKeyConfig;
import com.batata.continuing.service.common.RedisService;
import com.batata.continuing.utils.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;


/**
 * ip 相关的统计
 */
@Component
public class IpCount {


    /**
     * 封装的redis方法
     */
    @Autowired
    private RedisService redisService;


    @Autowired
    public RedisTemplate redisTemplate;


    /**
     * ip 是否可以继续访问
     *
     * @param url      访问的url
     * @param ip       访问的ip
     * @param maxValue 最大的访问次数
     * @param time     时间范围
     * @return
     */
    public boolean ipIsOk(String url, String ip, int maxValue, long time) {
        boolean ipIsOk = true;

        String key = RedisKeyConfig.ipCount + ip + url; // 拼接指定规则的key

        List<Long> timeList = redisService.getCacheList(key); // 查询redis中已有的数据


        if (
                timeList.size() == 0 || timeList.size() < maxValue
        ) { // 没有记录或者没有达到最大访问次数不做超时验证
            addNewTime(key, time); // 添加当前的时间到list中
            return ipIsOk;

        } // 若不满足此条件，则证明list中的值达到了最大数量（即访问的次数）

        // 判断达到规定的访问次数的用时是否小于规定的时间
        if (
                (DateUtils.getNowTimeLong() - timeList.get(0)) < (time * 1000)
        ) {
            // 未达到，证明指定范围时间内访问数量超过的定义数量
            ipIsOk = false;
        }

        // 删除第一个值（就是时间最旧的那个值，我这边是下标为0的，手动在redis客户端测试的为row最大的值。这个根据自己的具体情况）
        redisTemplate.opsForList().remove(key, 1, timeList.get(0));
        addNewTime(key, time); // 添加当前的时间到list中

        return ipIsOk;
    }

    /**
     * 往redis中添加新的数据，注：新增的值row在后
     *
     * @param key  key
     * @param time 时间戳
     */
    public void addNewTime(String key, long time) {
        List<Long> nowTime = new ArrayList<>();
        nowTime.add(DateUtils.getNowTimeLong());
        redisService.setCacheList(key, nowTime);
        redisService.expire(key, time + 1); // 设置有效时间
    }


}
